<template>
  <div class="container">
    <AiWelcome v-if="isWelCome" @go="handleGo"></AiWelcome>
    <div v-else class="content">

        <div :class="showLeft ? 'cleft cleftOpen' : 'cleft cleftClose'">
          <div v-show="showLeft" style="display: flex;flex-direction: column;height: 100%">
            <div>
              <header  style="display: flex; justify-content: space-between; align-items: center;margin-bottom: 10px">
                <h1
                    class="koala-title"
                    :style="{transform: showLeft ? 'scaleX(1)' : 'scaleX(0)', opacity: showLeft ? 1 : 0}"
                    style="margin: 0; font-size: 35px; letter-spacing: 3px;"
                >
                  Koala
                </h1>
                <MenuFoldIcon  @click="showLeft = false" style="font-size: 25px; cursor: pointer;" />
              </header>
              <div>
                <t-button @click="handleNewChat" shape="round">
                  <template #icon ><GestureOpenIcon  style="font-size: 25px"/></template>
                  开启新对话</t-button>
              </div>
            </div>

            <ul style="margin-top: 20px;flex: 1;overflow-y: auto;overflow-x: hidden;min-width: 250px">
              <li @click="handleChangeList(item , index)" v-for="(item , index) in chatHistoryList"
                  :class="currentIndex === index ? 'chat-item active' : 'chat-item'">
                <span style="width: 80%;text-wrap: nowrap;text-overflow: ellipsis;overflow: hidden;">
                  {{ item.chatList[0].content}}
                </span>
                <span class="moreContainer">
                  <EllipsisIcon class="more" />
                  <ul class="moreContent">
                    <li @click.prevent.stop="handleDelete(item.sessionId)" style="color: red">
                      <Delete1Icon style="margin-right: 10px" />
                      删除
                    </li>
                  </ul>
                </span>

              </li>
            </ul>
          </div>
          <div v-show="!showLeft" style="display: flex;flex-direction: column;align-items: center;">
            <img style="width: 40px;margin-bottom: 40px;transform: scale(1.5)" src="@/assets/logo2.png">

            <t-tooltip content="打开侧边栏" style="">
            <MenuFoldIcon @click="showLeft = true" style="font-size: 25px; cursor: pointer;margin-bottom: 20px" />
            </t-tooltip>

            <t-tooltip content="开启新对话">
              <GestureOpenIcon  @click="handleNewChat" style="font-size: 25px; cursor: pointer;"/>
            </t-tooltip>
          </div>


        </div>
      <div class="cright">
        <t-chat
            ref="chatRef"
            :clear-history="false"
            @scroll="handleChatScroll"
            @clear="clearConfirm"
        >


          <template v-for="(item, index) in chatList" :key="index">
            <t-chat-item
                v-show="!isLoading"
                :avatar="item.avatar"
                :name="item.name"
                :role="item.role"
                :datetime="item.datetime"
                :text-loading="index === 0 && loading"
                :content="item.content"
                :reasoning="useModel == 'r1' ? {
                    expandIconPlacement: 'right',

                    collapsePanelProps: {
                      header: renderHeader(index === 0 && isStreamLoad, item),
                      content: renderReasoningContent(item.reasoning),
                    },
                } : false"
            >
              <template #actions="content">
              <t-chat-action
                  :content="item.content"
                  :operation-btn="[ 'copy']"
              />
            </template>
            </t-chat-item>

          </template>
          <ChatSkeleton v-show="isLoading"></ChatSkeleton>
          <template #footer>
            <t-chat-sender
                :stop-disabled="isStreamLoad"
                :textarea-props="{
                   placeholder: '请输入消息...',
                }"
                @stop="onStop"
                @send="inputEnter"
            >
              <template #prefix>
                <div class="model-select">
<!--                  <t-tooltip v-model:visible="allowToolTip" content="切换模型" trigger="hover">
                    <t-select
                        v-model="selectValue"
                        :options="selectOptions"
                        value-type="object"
                        @focus="allowToolTip = false"
                    ></t-select>
                  </t-tooltip>-->
                  <t-button class="check-box" :class="{ 'is-active': isChecked }" variant="text" @click="checkClick">
                    <SystemSumIcon style="position: relative;top: 2px"/>
                    <span>深度思考</span>
                  </t-button>
                </div>
              </template>
            </t-chat-sender>
          </template>
        </t-chat>
        <t-button v-show="isShowToBottom" variant="text" class="bottomBtn" @click="backBottom">
          <div class="to-bottom">
            <ArrowDownIcon />
          </div>
        </t-button>

      </div>
    </div>
  </div>
</template>

<script setup lang="jsx">
import AiWelcome from "@/components/AiWelcome.vue";
import {onMounted, ref, triggerRef} from "vue";
import { ArrowDownIcon, SystemSumIcon , MenuFoldIcon , GestureOpenIcon , EllipsisIcon , Delete1Icon} from 'tdesign-icons-vue-next';
import { CheckCircleIcon } from 'tdesign-icons-vue-next';
import {reqChatDetail, reqChatList, reqChatStream, reqDelChat} from "@/api/ai/index.js";
import {useUserStore} from "@/stores/modules/user.js";
import ChatSkeleton from "@/components/ChatSkeleton.vue";

const isLoading = ref(false);
const currentSessionId = ref('')
const userStore = useUserStore()
const isWelCome = ref(true)
const useModel = ref('v3')
const handleGo = () => {
  isWelCome.value = false
}

const chatHistoryList = ref({})
const showLeft = ref(false);
const currentIndex = ref(-1)
onMounted(() => {
  getChatList()
  handleNewChat()
  // setTimeout(() => {
  //   showLeft.value = false
  // } , 2000)
})
// 开启新对话
const handleNewChat = () => {
  currentSessionId.value = ''
  currentIndex.value = -1
  chatList.value = []
  chatList.value.push( {
    avatar: 'https://miaoying-yuanding-space.oss-cn-beijing.aliyuncs.com/logo2.png',
    name: 'Koala',
    datetime: new Date().toDateString(),
    content: getLuXunStyleGreeting(userStore.nickName),
    reasoning: false,
    role: 'assistant',
  })
  chatList.value.push({
    content: `您开启了新的对话`,
    role: 'model-change',
    reasoning: '',
  })
}

// 点击删除聊天
const handleDelete = async (id ) => {
  const res = await reqDelChat(id);
  getChatList()
  if (currentSessionId.value === id) {
      handleNewChat()
  }
}

// 切换历史聊天记录
const handleChangeList = async (chat , index) => {
  isLoading.value = true
  currentIndex.value = index
  currentSessionId.value = chat.sessionId
  const res =  await reqChatDetail(chat.sessionId)

  chatList.value = res.data.map(item => {
        if (item.role === 'user') {
          item.avatar = userStore.avatar;
          item.name = '自己';
        } else {
          item.avatar = 'https://miaoying-yuanding-space.oss-cn-beijing.aliyuncs.com/logo2.png';
          item.name = 'Koala';
        }
        return item;
      }
  ).filter(item => item.role !== 'system').reverse()
    chatList.value.unshift({
      content: `您进入了一个历史会话`,
      role: 'model-change',
      reasoning: '',
    })
  isLoading.value = false
}

// 获取用户列表
const getChatList = () => {
  reqChatList().then((res) => {

    const tempArr = []

    for (const item in res.data) {
      tempArr.push({sessionId: item , chatList: res.data[item].filter(item => item.role !== 'system')})
    }
    chatHistoryList.value = tempArr;
  })
}

function getRandomPoemLine() {
  const poems = [
    "东隅已逝，桑榆非晚",
    "海内存知己，天涯若比邻",
    "人生若只如初见，何事秋风悲画扇",
    "但愿人长久，千里共婵娟",
    "春江潮水连海平，海上明月共潮生",
    "莫等闲，白了少年头，空悲切",
    "采菊东篱下，悠然见南山",
    "路漫漫其修远兮，吾将上下而求索",
    "山重水复疑无路，柳暗花明又一村",
    "千山鸟飞绝，万径人踪灭"
  ];

  const randomIndex = Math.floor(Math.random() * poems.length);
  return poems[randomIndex];
}

function getLuXunStyleGreeting(nickname) {
  const lines = [
    "小心头顶高悬的达摩克利斯之剑！" + nickname,
    "今天过的怎么样！" + nickname,
    "有什么需要帮助的吗？" + nickname,
    "One for the money,One for the show.",
    "众里寻他千百度",
    "太阳会照常升起，" + nickname,
    "要致敬每一只仰望星空的猴子，" + nickname
  ];

  const randomIndex = Math.floor(Math.random() * lines.length);
  return lines[randomIndex];
}


const fetchCancel = ref(null);
const loading = ref(false);
// 流式数据加载中
const isStreamLoad = ref(false);

const chatRef = ref(null);
const isShowToBottom = ref(false);
// 滚动到底部
const backBottom = () => {
  chatRef.value.scrollToBottom({
    behavior: 'smooth',
  });
};
const selectOptions = [
  {
    label: 'DeepSeekV3',
    value: 'v3',
  }
];
const selectValue = ref({
  label: 'DeepSeekV3',
  value: 'v3',
});
const allowToolTip = ref(false);
const isChecked = ref(false);
const checkClick = () => {
  isChecked.value = !isChecked.value;
  if (isChecked.value) {
    useModel.value = 'r1'
    chatList.value.unshift(  {
      content: `模型由<span>deepSeek V3</span>变为<span>deepSeek R1</span>`,
      role: 'model-change',
      reasoning: '',
    },)
  } else {
    chatList.value.unshift(  {
      content: `模型由<span>deepSeek R1</span>变为<span>deepSeek V3</span>`,
      role: 'model-change',
      reasoning: '',
    },)
    useModel.value = 'v3'
  }
};
const handleChange = (value, { index }) => {
  console.log('handleChange', value, index);
};
/**
 * 渲染推理模块的头部自定义内容
 * @param {boolean} flag - 思维链内容是否加载中
 * @param {string} endText - 思维链加载完成时显示的文本
 * @returns {JSX.Element} 返回对应的头部组件
 */
const renderHeader = (flag, item) => {
  if (flag) {
    return <t-chat-loading text="思考中..." />;
  }
  const endText = item.duration ? `已深度思考(用时${item.duration}秒)` : '已深度思考';
  return (
      <div style="display:flex;align-items:center">
        <CheckCircleIcon
            style={{
              color: 'var(--td-success-color-5)',
              fontSize: '20px',
              marginRight: '8px',
            }}
        />
        <span>{endText}</span>
      </div>
  );
};
const renderReasoningContent = (reasoningContent) => <t-chat-content content={reasoningContent} role="assistant" />;
// 倒序渲染
const chatList = ref([
//   {
//     content: `模型由<span>hunyuan</span>变为<span>GPT4</span>`,
//     role: 'model-change',
//     reasoning: '',
//   },
//   {
//     avatar: 'https://tdesign.gtimg.com/site/chat-avatar.png',
//     name: 'TDesignAI',
//     datetime: '今天16:38',
//     reasoning: `嗯，用户问牛顿第一定律是不是适用于所有参考系。首先，我得先回忆一下牛顿第一定律的内容。牛顿第一定律，也就是惯性定律，说物体在没有外力作用时会保持静止或匀速直线运动。也就是说，保持原来的运动状态。
//
// `,
//     content: `牛顿第一定律（惯性定律）**并不适用于所有参考系**，它只在**惯性参考系**中成立。以下是关键点：
//
// ---
//
// ### **1. 牛顿第一定律的核心**
// - **内容**：物体在不受外力（或合力为零）时，将保持静止或匀速直线运动状态。
// - **本质**：定义了惯性系的存在——即存在一类参考系，在其中惯性定律成立。
//
// ---
// `,
//     role: 'assistant',
//     duration: 10,
//   },
//   {
//     avatar: 'https://tdesign.gtimg.com/site/avatar.jpg',
//     name: '自己',
//     datetime: '今天16:38',
//     content: '牛顿第一定律是否适用于所有参考系？',
//     role: 'user',
//     reasoning: '',
//   },
]);
const clearConfirm = function () {
  chatList.value = [];
};
const onStop = function () {
  loading.value = false;
  isStreamLoad.value = false;
};
// 是否显示回到底部按钮
const handleChatScroll = function ({ e }) {
  const scrollTop = e.target.scrollTop;
  isShowToBottom.value = scrollTop < 0;
};

// 回车输入
const inputEnter = function (inputValue) {
  if (isStreamLoad.value) {
    return;
  }
  if (!inputValue) return;
  const params = {
    avatar: userStore.avatar,
    name: '自己',
    datetime: new Date().toDateString(),
    content: inputValue,
    role: 'user',
  };
  chatList.value.unshift(params);

  if (!currentSessionId.value) {
    const uuid = crypto.randomUUID()
    currentSessionId.value = uuid;
  }

  // 空消息占位
  const params2 = {
    avatar: 'https://miaoying-yuanding-space.oss-cn-beijing.aliyuncs.com/logo2.png',
    name: 'Koala',
    datetime: new Date().toDateString(),
    content: '',
    reasoning: '',
    role: 'assistant',
  };
  chatList.value.unshift(params2);
  handleData(inputValue);
};
const handleData = async (inputValue) => {
  loading.value = true;
  isStreamLoad.value = true;
  const startTime = new Date();
  const lastItem = chatList.value[0];

  const reqObj = {userId : userStore.userId ,
    question: inputValue ,
    model: useModel.value,
    sessionId: currentSessionId.value,
  }
  let flag = true;
  reqChatStream(reqObj ,
      {
        onMessage: (data) => {
          loading.value = false;
          if (data.type == 0) {
            lastItem.reasoning = data.reasoningContent;
          } else if (data.type == 1) {
            // 显示用时xx秒
            if (flag) {

            }
            flag =false
            lastItem.content = data.content;
          } else if (data.type == 8) {
              const sessionId = data.content;
              currentSessionId.value = sessionId;
              chatHistoryList.value.unshift({sessionId: sessionId, chatList: [{content: inputValue}] });
              currentIndex.value = 0
          }
          if (data.sessionId) {
            currentSessionId.value = data.sessionId;
          }
        },
        onComplete: () => {
          console.log('结束')
          lastItem.duration = (new Date().getTime() - startTime.getTime()) / 1000;
          loading.value = false;
          // 控制终止按钮
          isStreamLoad.value = false;
          // if (chatList.value.length <= 3) {
          //   chatHistoryList.value.unshift({sessionId: currentSessionId.value, chatList: [{content: inputValue}] });
          //   currentIndex.value = 0
          // }

        },
        onError: (err) => {

        }
      })

/*  const mockedData = {
    reasoning: `嗯，用户问牛顿第一定律是不是适用于所有参考系。首先，我得先回忆一下牛顿第一定律的内容。牛顿第一定律，也就是惯性定律，说物体在没有外力作用时会保持静止或匀速直线运动。也就是说，保持原来的运动状态。

那问题来了，这个定律是否适用于所有参考系呢？记得以前学过的参考系分惯性系和非惯性系。惯性系里，牛顿定律成立；非惯性系里，可能需要引入惯性力之类的修正。所以牛顿第一定律应该只在惯性参考系中成立，而在非惯性系中不适用，比如加速的电梯或者旋转的参考系，这时候物体会有看似无外力下的加速度，所以必须引入假想的力来解释。`,
    content: `牛顿第一定律（惯性定律）**并不适用于所有参考系**，它只在**惯性参考系**中成立。以下是关键点：

---

### **1. 牛顿第一定律的核心**
- **内容**：物体在不受外力（或合力为零）时，将保持静止或匀速直线运动状态。
- **本质**：定义了惯性系的存在——即存在一类参考系，在其中惯性定律成立。`,
  };
  const mockResponse = new MockSSEResponse(mockedData);
  fetchCancel.value = mockResponse;
  await fetchSSE(
      () => {
        return mockResponse.getResponse();
      },
      {
        success(result) {
          console.log('success', result);
          loading.value = false;
          lastItem.reasoning += result.delta.reasoning_content;
          lastItem.content += result.delta.content;
        },
        complete(isOk, msg) {
          if (!isOk) {
            lastItem.role = 'error';
            lastItem.content = msg;
            lastItem.reasoning = msg;
          }
          // 显示用时xx秒，业务侧需要自行处理
          lastItem.duration = 20;
          // 控制终止按钮
          isStreamLoad.value = false;
          loading.value = false;
        },
      },
  );*/
};

</script>

<style scoped lang="less">
.active {
  background-color: rgba(129, 129, 129 , 0.4);
}

/deep/ .t-chat__avatar-image {
  width: 40px;
  height: 40px;
  object-fit: contain;
}

.chat-item:hover {
  background-color: rgb(60, 60, 60);
}

.moreContainer {
  position: relative;

}
.moreContent {
  position: absolute;
  background-color: rgba(83, 83, 83, 0.9);
  padding: 10px;
  display: none;
  transition: 1s;
  opacity:  0;
  right: -20px;
  width: 120px;
  border-radius: 10px;
}

.moreContent li:hover {
  background-color: rgba(108, 108, 108, 0.8);
  border-radius: 3px;
  user-select: none;
}


.moreContent li {
  display: flex;
  align-items: center;
  padding: 5px 10px;

}

.moreContainer:hover .moreContent {
  opacity: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.more {
  display: none;
  transform: scale(1.9);
}
.chat-item:hover .more {
  background-color: rgb(60, 60, 60);
  display: inline-block;
}


.chat-item {
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  box-sizing: border-box;
  border-radius: 10px;
  padding: 5px 20px 5px 10px;
  font-size: 14px;
  margin-bottom: 5px;
  align-items: center;
}

.cleftOpen {
  width: 300px;
  padding: 20px;
}

.cleftClose {
  width:80px;
  padding: 20px;
}

.cleft {

  background: rgb(33, 35, 39);
  flex-shrink: 0; /* 防止左侧被压缩 */
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  color: rgb(171, 178, 189);
  transition: all 0.5s ease;
  transform-origin: right center;
  overflow: hidden;
}

.cright {
  flex: 1;
  padding: 30px 100px;
  display: flex;
  justify-content: center;
}

.content {
  width: 100%;
  height: 100%;
  color: rgb(248, 250, 255);
  display: flex;

}

.container {
  width: 98%;
  height: 100%;
  border-radius: 25px;
  background: rgb(41, 42, 45);
  max-width: 10000px !important;
  overflow: hidden;
}




/* 应用滚动条样式 */
::-webkit-scrollbar-thumb {
  background-color: var(--td-scrollbar-color);
}
::-webkit-scrollbar-thumb:horizontal:hover {
  background-color: var(--td-scrollbar-hover-color);
}
::-webkit-scrollbar-track {
  background-color: var(--td-scroll-track-color);
}
.cright {
  position: relative;
  .bottomBtn {
    position: absolute;
    left: 50%;
    margin-left: -20px;
    bottom: 170px;
    padding: 0;
    border: 0;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.08), 0px 16px 24px 2px rgba(0, 0, 0, 0.04),
    0px 6px 30px 5px rgba(0, 0, 0, 0.05);
  }
  .to-bottom {
    width: 40px;
    height: 40px;
    border: 1px solid #dcdcdc;
    box-sizing: border-box;
    background: var(--td-bg-color-container);
    border-radius: 50%;
    font-size: 24px;
    line-height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    .t-icon {
      font-size: 24px;
    }
  }
}

.model-select {
  display: flex;
  align-items: center;
  .t-select {
    width: 112px;
    height: var(--td-comp-size-m);
    margin-right: var(--td-comp-margin-s);
    .t-input {
      border-radius: 32px;
      padding: 0 15px;
    }
    .t-input.t-is-focused {
      box-shadow: none;
    }
  }
  .check-box {
    width: 112px;
    height: var(--td-comp-size-m);
    border-radius: 32px;
    border: 0;
    background: var(--td-bg-color-component);
    color: var(--td-text-color-primary);
    box-sizing: border-box;
    flex: 0 0 auto;
    .t-button__text {
      display: flex;
      align-items: center;
      justify-content: center;
      span {
        margin-left: var(--td-comp-margin-xs);
      }
    }
  }
  .check-box.is-active {
    border: 1px solid var(--td-brand-color-focus);
    background: var(--td-brand-color-light);
    color: var(--td-text-color-brand);
  }
}
</style>
